package util;

import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Spliterator;
import java.util.function.Consumer;

public class StackConcatenato<T> implements Stack<T> {

	private class StackIterator implements Iterator<T> {// da fare
		private Nodo<T> pre = null, cor = null;

		@Override
		public boolean hasNext() {
			if (cor == null)
				return testa != null;

			return cor.next != null;
		}

		@Override
		public T next() {
			if (!hasNext())
				throw new NoSuchElementException();

			if (cor == null)
				cor = testa;
			else {
				pre = cor;
				cor = cor.next;

			}
			return cor.info;

		}// next

		@Override
		public void remove() {
			if (pre == cor)
				throw new IllegalStateException();
			if (cor == testa)
				testa = cor.next;
			else
				pre.next = cor.next;
			cor = pre;// arretra cor.
			size--;
		}// remove

		@Override
		public void forEachRemaining(Consumer<? super T> arg0) {
			// TODO Auto-generated method stub

		}

	}

	private static class Nodo<E> {
		E info;
		Nodo<E> next;

	}

	private int size;
	private Nodo<T> testa = null;

	@Override
	public int size() {
		return size;
	}

	@Override
	public void clear() {

		testa = null;
		size = 0;
		// il garbage collector provvede ad eliminare tutti gli altri elementi
		// visto che macano i riferimenti.
	}

	@Override
	public void push(T x) {

		Nodo<T> nw = new Nodo<>();
		nw.info = x;
		nw.next = testa;
		testa = nw;

	}// push

	@Override
	public T pop() {
		if (size == 0)
			throw new NoSuchElementException();

		T y = testa.info;
		testa = testa.next;
		size--;

		return y;
	}

	@Override
	public T top() {
		if (size == 0)
			throw new NoSuchElementException();

		return testa.info;
	}

	@Override
	public boolean isEmpty() {// TODO Auto-generated method stub
		return size == 0;
	}

	@Override
	public boolean isFull() {

		return false;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

	@Override
	public Iterator<T> iterator() {
		return new StackIterator();

	}

	public String toString() {
		StringBuilder sb = new StringBuilder(200);
		sb.append('[');
		Iterator<T> it = this.iterator();
		while (it.hasNext()) {
			sb.append(it.next());
			if (it.hasNext())
				sb.append(", ");

		}
		sb.append(']');
		return toString();

	}

	public boolean equals(Object x) {
		if (!(x instanceof Stack))
			return false;
		if (x == this)
			return true;
		Stack<T> s = (Stack<T>) x;
		if (size != s.size())
			return false;
		Iterator<T> it = s.iterator();
		Nodo<T> cor = testa;
		while (cor != null) {
			T x1 = cor.info, x2 = it.next();
			if (!x1.equals(x2))
				return false;
			cor = cor.next;

		}
		return true;

	}

	public int hashCode() {
		final int mol = 83;
		int h = 0;
		Nodo<T> cor = testa;
		while (cor != null) {
			h = h * mol + cor.info.hashCode();
			cor = cor.next;
		}
		return h;

	}

	@Override
	public Spliterator<T> spliterator() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void forEach(Consumer<? super T> arg0) {
		// TODO Auto-generated method stub

	}

}
